package com.goldsprite.gameframeworks.shaders;

import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.goldsprite.gameframeworks.ecs.system.*;
import com.goldsprite.gameframeworks.log.*;
import com.goldsprite.gameframeworks.utils.*;
import com.goldsprite.gameframeworks.utils.math.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class AmbientLightShader extends BaseShader {
	private int uTextureLocation;
	private int uTimeLocation;
	private int uDayTimeLocation;

	private int uViewSizeLocation;
	private int uLightDataTextureLocation;
	private int uLightPosition2dLocation;
	private int uLightAmountLocation;
	private int uLightIntensityCompressValLocation;

	public float uTime;
	private float realTime;
	private float dayTimeSeconds = 3f * 60;//3分钟一个昼夜

	public boolean enableDayNightPass = true;
	public boolean enablePointLightPass = true;
	private int maxLightSources = 2048; // 最大光源数量
	public float lightIntensityCompressVal = 100.0f;//光源强度数据压缩
	public List<LightSource> lightSources;
	private boolean isLightSourcesDirty;
	public Texture lightDataTexture;//rgba分别表示: rg->xy, b->colorIndex, a->lightIntensity
	private Pixmap lightDataPixmap;
	public boolean timePause;

	public AmbientLightShader() {
		super("shaders/ambient_light.vert", "shaders/ambient_light.frag");
		initLightDataTexture();
	}

	@Override
	protected void initUniforms() {
		uTextureLocation = shaderProgram.getUniformLocation("u_texture");

		uTimeLocation = shaderProgram.getUniformLocation("u_time");
		uDayTimeLocation = shaderProgram.getUniformLocation("u_dayTime");

		uViewSizeLocation = shaderProgram.getUniformLocation("u_viewSize");
		uLightPosition2dLocation = shaderProgram.getUniformLocation("u_lightPosition2d");
		uLightAmountLocation = shaderProgram.getUniformLocation("u_lightAmount");
		uLightDataTextureLocation = shaderProgram.getUniformLocation("u_lightDataTexture");
		uLightIntensityCompressValLocation = shaderProgram.getUniformLocation("u_lightIntensityCompressVal");
	}

	@Override
	public void setUniforms() {
		if (isLightSourcesDirty()) {
			updateAllLightSources();
		}
		shaderProgram.setUniformi(uTextureLocation, 0);

		setUniformf(uTimeLocation, uTime);
		setUniformf(uDayTimeLocation, dayTimeSeconds);

		float viewWidth = GameSystem.uiViewport.getWorldWidth();
		float viewHeight = GameSystem.uiViewport.getWorldHeight();

		shaderProgram.setUniformf(uViewSizeLocation, viewWidth, viewHeight);
		shaderProgram.setUniformi(uLightAmountLocation, getLightAmount());
		shaderProgram.setUniformi(uLightDataTextureLocation, 1);
		lightDataTexture.bind(1);
		lightDataTexture.bind(0);
		shaderProgram.setUniformf(uLightIntensityCompressValLocation, lightIntensityCompressVal);
	}

	@Override
	public void update(float delta) {
		if(!timePause){
			uTime += delta;
		}

		realTime = (uTime * 24.0f + 6 * dayTimeSeconds) / 24.0f;//将开始时间偏移到正午12点, 因为为0时shader最亮

		float curDays = realTime / dayTimeSeconds;
		float curTime = curDays % dayTimeSeconds;
		int curIntDay = (int) (curDays - curTime);
		long dateTimeNanos = (long) (curDays * TimeUtils.Day2Nanos);
		long dateNanos = (long) (curIntDay * TimeUtils.Day2Nanos);
		long timeNanos = (long) (curTime * TimeUtils.Day2Nanos);
		String curFormatDateTime = TimeUtils.formatRelativeTime(dateTimeNanos, "yyyy年MM月dd日 HH时mm分ss秒");
		String curFormatDate = TimeUtils.formatRelativeTime(dateNanos, "yyyy年MM月dd日");
		String curFormatTime = TimeUtils.formatRelativeTime(timeNanos, "HH时mm分ss秒");
		Debug.infoT("Shader", "当前天数: %s", curIntDay);
		Debug.infoT("Shader", "游戏全日期: %s", curFormatDateTime);
		Debug.infoT("Shader", "游戏日期: %s", curFormatDate);
		Debug.infoT("Shader", "时间(24H): %s", curFormatTime);

		//应用速度
		boolean dirty = false;
		for (LightSource light : lightSources) {
			if (light == null) continue;
			if(!light.velocity.isZero()){
				dirty = true;
				try(Vector2 deltaVel = Vector2.obtain(light.velocity).scl(delta)){
					light.position.add(deltaVel);
					light.position.clamp(0f, 1f);
				}
			}
		}
		if(dirty) setLightSourcesDirty(true);
	}

	public void setDayTimeMinutes(float dayTimeMinutes) {
		setDayTimeSeconds(dayTimeMinutes * 60);
	}

	public void setDayTimeSeconds(float dayTimeSeconds) {
		this.dayTimeSeconds = dayTimeSeconds;
	}

	private void initLightDataTexture() {
		// 创建maxLightSources x 1的纹理和Pixmap
		lightDataTexture = new Texture(maxLightSources, 1, Pixmap.Format.RGBA8888);
		lightDataPixmap = new Pixmap(maxLightSources, 1, Pixmap.Format.RGBA8888);

		// 初始化为全黑（无光源）
		lightDataPixmap.setColor(0, 0, 0, 0);
		lightDataPixmap.fill();
		updateLightDataTexture();

		// 初始化固定长度的光源列表
		lightSources = new ArrayList<>(maxLightSources);
		for (int i = 0; i < maxLightSources; i++) {
			lightSources.add(null); // 初始化为null表示空槽位
		}
	}

	public LightSource getLightSource(int index) {
		if (index < 0 || index >= lightSources.size()) return null;
		return lightSources.get(index);
	}

	// 添加光源，返回索引，如果满了返回-1
	public LightSource addPointLight(float worldX, float worldY, int colorIndex, float lightIntensity) {
		int index = findEmptySlot();
		if (index == -1) return null; // 没有空槽位
		return addPointLight(index, worldX, worldY, colorIndex, lightIntensity);
	}
	public LightSource addPointLight(int index, float worldX, float worldY, int colorIndex, float lightIntensity) {
		LightSource lightSource = new LightSource();
		lightSource.position.set(worldX, worldY);
		lightSource.colorIndex = colorIndex;
		lightSource.lightIntensity = lightIntensity;
		lightSources.set(index, lightSource);
		setLightSourcesDirty(true);

		return lightSource;
	}

	// 移除光源
	public void removeLightSource(int index) {
		if (index >= 0 && index < maxLightSources) {
			LightSource light = lightSources.get(index);
			if (light != null) {
				setLightSourcesDirty(true);
				lightSources.set(index, null);
			}
		}
	}

	// 更新光源属性
	public void updateLightSource(int index, float viewX, float viewY, Integer colorIndex, Float lightIntensity) {
		if (index >= 0 && index < maxLightSources) {
			LightSource light = lightSources.get(index);
			if (light != null) {
				if (viewX != -1) light.position.x = viewX;
				if (viewY != -1) light.position.y = viewY;
				if (colorIndex != null) light.colorIndex = colorIndex;
				if (lightIntensity != null) light.lightIntensity = lightIntensity;
				setLightSourcesDirty(true);
			}
		}
	}

	// 查找空槽位
	private int findEmptySlot() {
		for (int i = 0; i < maxLightSources; i++) {
			if (lightSources.get(i) == null) {
				return i;
			}
		}
		return -1;
	}

	// 更新所有光源数据到纹理
	public void updateAllLightSources() {
		// 清空Pixmap
		lightDataPixmap.setColor(0, 0, 0, 0);
		lightDataPixmap.fill();

		// 更新所有光源数据
		int maxLightSources = Math.min(this.maxLightSources, getLightAmount());
		for (int i = 0; i < maxLightSources; i++) {
			LightSource light = lightSources.get(i);

			if (light != null) {
				// 屏幕坐标归一化到[0,1]
				float normX = light.position.x;
				float normY = light.position.y;
				int colorIndex = light.colorIndex;
				float lightIntensity = light.lightIntensity / lightIntensityCompressVal;

				// 写入Pixmap
				lightDataPixmap.drawPixel(i, 0, Color.rgba8888(normX, normY, colorIndex, lightIntensity));
			}
			// 非活跃光源保持为0（黑色）
		}

		// 更新纹理
		updateLightDataTexture();
		setLightSourcesDirty(false);
	}

	public boolean isLightSourcesDirty() {
		return isLightSourcesDirty;
	}

	public void setLightSourcesDirty(boolean dirty) {
		isLightSourcesDirty = dirty;
	}

	// 获取有效光源数量
	public int getLightAmount() {
		int amount = (int) lightSources.stream().filter(Objects::nonNull).count();
		return amount;
	}

	public void updateLightDataTexture() {
		lightDataTexture.draw(lightDataPixmap, 0, 0);
	}
}
